class_name Entity
extends Node2D

## TODO 大部分执行逻辑都写在这里

#region 属性
## 需要设置local_to_scene
@export var entity_data:EntityData
@export var entity_state_additional_effect_dict:Dictionary[GameEnum.EntityState,AdditionalEffectInfo]
var components:Array[BaseComponent] = []
var init_args:Dictionary = {}
## 创造者
var creater:Entity
#endregion
#region 字段
@export var root:Node:
	get:
		if not root:
			root = get_parent()
		return root
## 物理Body（主要处理碰撞等）
@export var physics_body:CollisionShape2D:
	get:
		if not physics_body:
			physics_body = %PhysicsBody
		return physics_body
## 逻辑Body（主要处理检测）
@export var logical_body:Area2D:
	get:
		if not logical_body:
			logical_body = %LogicalBody
		return logical_body
#endregion
#region 信号
## 准备销毁时
signal destroying()
#endregion

#region 基类方法
#endregion
#region 公共方法
func set_init_args(args:Dictionary = {}):
	self.init_args = init_args
	creater = args.get("Creater",null)
func init():
	components.clear()
	for child in root.get_children():
		if child is BaseComponent:
			components.append(child)
	components.sort_custom(func(c0:BaseComponent,c1:BaseComponent):return c0.priority > c1.priority)
	Utils.array_for_each(components,func(c:BaseComponent):
		c.init_component(init_args)
		c.after_init_component()
		)
## 获得指定类型的组件
## 只支持找本身和直接子类这一层的相应类型
func get_component(component_type):
	return Utils.find_child_by_type(root,component_type,2)
## 销毁函数
func destroy():
	## 先发销毁信号，因为可能其它地方还需要entity_data
	destroying.emit()
	entity_data.destroy.call_deferred()
#region 虚函数
func change_vel(vel:Vector2):
	pass
func change_acc(acc:Vector2):
	pass
func add_rotation(rot:float):
	pass
#endregion
#endregion
#region 私有方法
#endregion
#region 生命周期函数
func _init() -> void:
	for additional_effect_info:AdditionalEffectInfo in entity_state_additional_effect_dict.values():
		for additional_effect:AdditionalEffect in additional_effect_info.addition_effects:
			additional_effect.init({Target = self,Owner = self})
	var additional_effect_info:AdditionalEffectInfo = entity_state_additional_effect_dict.get(GameEnum.EntityState.Init,null)
	if additional_effect_info:
		for additional_effect:AdditionalEffect in additional_effect_info.addition_effects:
			additional_effect.excute()
func _enter_tree() -> void:
	entity_data.init(self)
	for additional_effect_info:AdditionalEffectInfo in entity_state_additional_effect_dict.values():
		for additional_effect:AdditionalEffect in additional_effect_info.addition_effects:
			additional_effect.init({Target = self,Owner = self})
	var additional_effect_info:AdditionalEffectInfo = entity_state_additional_effect_dict.get(GameEnum.EntityState.Init,null)
	if additional_effect_info:
		for additional_effect:AdditionalEffect in additional_effect_info.addition_effects:
			additional_effect.excute()
	additional_effect_info = entity_state_additional_effect_dict.get(GameEnum.EntityState.EnterTree,null)
	if additional_effect_info:
		for additional_effect:AdditionalEffect in additional_effect_info.addition_effects:
			additional_effect.excute()
func _ready() -> void:
	init()
	var additional_effect_info:AdditionalEffectInfo = entity_state_additional_effect_dict.get(GameEnum.EntityState.Ready,null)
	if additional_effect_info:
		for additional_effect:AdditionalEffect in additional_effect_info.addition_effects:
			additional_effect.excute()
func _process(delta: float) -> void:
	var additional_effect_info:AdditionalEffectInfo = entity_state_additional_effect_dict.get(GameEnum.EntityState.Progress,null)
	if additional_effect_info:
		for additional_effect:AdditionalEffect in additional_effect_info.addition_effects:
			additional_effect.excute()
func _physics_process(delta: float) -> void:
	var additional_effect_info:AdditionalEffectInfo = entity_state_additional_effect_dict.get(GameEnum.EntityState.PhysicsProgress,null)
	if additional_effect_info:
		for additional_effect:AdditionalEffect in additional_effect_info.addition_effects:
			additional_effect.excute()
func _exit_tree() -> void:
	var additional_effect_info:AdditionalEffectInfo = entity_state_additional_effect_dict.get(GameEnum.EntityState.ExitTree,null)
	if additional_effect_info:
		for additional_effect:AdditionalEffect in additional_effect_info.addition_effects:
			additional_effect.excute()
func _notification(what: int) -> void:
	if what == NOTIFICATION_PREDELETE:
		var additional_effect_info:AdditionalEffectInfo = entity_state_additional_effect_dict.get(GameEnum.EntityState.Destroy,null)
		if additional_effect_info:
			for additional_effect:AdditionalEffect in additional_effect_info.addition_effects:
				additional_effect.excute()
		destroy()
#endregion
